/*
 * fixedtree.cpp
 *
 *  Created on: Mar 30, 2011
 *      Author: Mo
 */

#include "fixedtree.h"
#include "freefuncs.h"
#include <math.h>
#include "cmconstants.h"
#include <iostream>

int FixedTree::getEmptyNodeNum() {return this->emptyNodeNum;}
int FixedTree::getNodeNum() {return this->nodeNum;}
int FixedTree::getnonEmptyNodeNum() {return this->nonEmptyNodeNum;}

void FixedTree::print(void)
{
	int ruleSize = rootRB.getInstanceSize();
	int levelNum = ruleSize+1;
	int nodesInThisLevel;
	cout << "FTC: Feature To Check, LBL: Label (0:White, 1:Black, 2:Not Yet 3:Blank.";
	for (int row = 0; row != levelNum; row++)
	{
		nodesInThisLevel = intPosPow(CELLSTATES,row);
		cout << endl << "LEVEL " << row << ": ";
		for (int index = 0; index != nodesInThisLevel; index++)
			cout << "(" << this->node[row][index].getFeatureToCheck() << "," <<
				this->node[row][index].getNodeDecision() << ")\t";
	}
}

FixedTree::FixedTree()
{
	//int nodesInThisLevel = 0;
	this->averageDepth = 0;
	this->emptyNodeNum = 0;
	this->nodeNum = 0;
	this->nonEmptyNodeNum = 0;
}

FixedTree::FixedTree(FixedTree& other)
{
	int ruleSize = other.rootRB.getInstanceSize();
	int nodesInThisLevel = 0;
	this->averageDepth = other.averageDepth;
	this->emptyNodeNum = other.emptyNodeNum;
	this->nodeNum = other.nodeNum;
	this->rootRB = other.rootRB;
	this->nonEmptyNodeNum = other.nonEmptyNodeNum;
	this->node = new FixedTreeNode* [ruleSize];
	for (int i = 0; i != ruleSize; i++)
	{
		nodesInThisLevel = intPosPow(CELLSTATES,i);
		node[i] = new FixedTreeNode[nodesInThisLevel];
		for (int j = 0; j != nodesInThisLevel; j++)
			this->node[i][j] = other.node[i][j];
	}
}


FixedTree::FixedTree (RuleBase& rb)
{
	int ruleSize = rb.getInstanceSize();
	int levelNum = ruleSize+1;
	this->rootRB = RuleBase(rb);
	int nodesInThisLevel = 0;
	this->averageDepth = 0;
	this->emptyNodeNum = 0;
	this->nodeNum = 0;
	this->nonEmptyNodeNum = 0;
	this->node = new FixedTreeNode* [levelNum]; 
	for (int i = 0; i != levelNum; i++)
	{
		nodesInThisLevel = intPosPow(CELLSTATES,i);
		node[i] = new FixedTreeNode[nodesInThisLevel];
		for (int j = 0; j != nodesInThisLevel; j++)
			node[i][j].makeArraysOfBlankNode(ruleSize);
		this->nodeNum += nodesInThisLevel;
	}
	
	this->node[0][0].setAsRoot(rb);

	for (int levelIndex = 1; levelIndex != levelNum; levelIndex++)
	{
		nodesInThisLevel = intPosPow(CELLSTATES,levelIndex);
		for (int j = 0; j != nodesInThisLevel; j++)
			node[levelIndex][j].updateFromParent((int)j%CELLSTATES, this->node[levelIndex-1][(int)j/CELLSTATES]);
	}

	for (int levelIndex = 0; levelIndex != levelNum; levelIndex++)
		{
			nodesInThisLevel = intPosPow(CELLSTATES,levelIndex);
			for (int j = 0; j != nodesInThisLevel; j++)
				if (this->node[levelIndex][j].getNodeDecision() == dblank)
					this->emptyNodeNum++;
		}
	this->nonEmptyNodeNum = this->nodeNum - this->emptyNodeNum;
}

FixedTree::~FixedTree()
{
	int ruleSize = this->rootRB.getInstanceSize();
	this->averageDepth = 0;
	this->emptyNodeNum = 0;
	this->nodeNum = 0;
	this->nonEmptyNodeNum = 0;
	for (int i = 0; i != ruleSize; i++)
		delete[] node[i];
	delete[] node;
}
